package com.kotiln.lgc.lib_network.net;


import androidx.appcompat.app.AppCompatDialog;


import com.kotiln.lgc.lib_network.net.callback.IError;
import com.kotiln.lgc.lib_network.net.callback.IFailure;
import com.kotiln.lgc.lib_network.net.callback.IRequest;
import com.kotiln.lgc.lib_network.net.callback.ISuccess;
import com.kotiln.lgc.lib_network.net.callback.RequestCallbacks;
import com.kotiln.lgc.lib_network.net.download.DownloadHandler;

import java.io.File;
import java.util.Map;
import java.util.WeakHashMap;

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.Callback;


public class RestClient {

    private final String URL;
    private final WeakHashMap<String, Object> PARAMS = RestCreator.getParams();
    private final IRequest REQUEST;
    private final String DOWNLOAD_DIR;
    private final String EXTENSION;
    private final String NAME;
    private final ISuccess SUCCESS;
    private final IError ERROR;
    private final IFailure FAILURE;
    private final RequestBody BODY;
    private final File FILE;
    private final AppCompatDialog DIALOG;

    public RestClient(String url, Map<String, Object> params, String downloadDir, String extension, String name, IRequest iRequest, ISuccess iSuccess, IError iError, IFailure iFailure, RequestBody body, File file, AppCompatDialog dialog) {
        this.URL = url;
        this.PARAMS.putAll(params);
        this.DOWNLOAD_DIR = downloadDir;
        this.EXTENSION = extension;
        this.NAME = name;
        this.REQUEST = iRequest;
        this.SUCCESS = iSuccess;
        this.ERROR = iError;
        this.FAILURE = iFailure;
        this.BODY = body;
        this.FILE = file;
        this.DIALOG = dialog;
    }

    public static RestClientBuilder builder() {
        return new RestClientBuilder();
    }

    private void request(HttpMethod method) {
        final RestService service = RestCreator.getRestService();
        Call<String> call = null;
        if(REQUEST != null)
        {
            REQUEST.onRequestStart();
        }

        if(DIALOG != null)
        {
            DIALOG.show();
        }

        switch (method) {
            case GET:
                call = service.get(URL, PARAMS);
                break;
            case POST:
                call = service.post(URL, PARAMS);
                break;
            case POST_RAW:
                call = service.postRaw(URL, BODY);
                break;
            case PUT:
                call = service.put(URL, PARAMS);
                break;
            case PUT_RAW:
                call = service.putRaw(URL, BODY);
                break;
            case DELETE:
                call = service.delete(URL, PARAMS);
                break;
            case UPLOAD:
                final RequestBody requestBody = RequestBody.create(MediaType.parse(MultipartBody.FORM.toString()), FILE);
                final MultipartBody.Part body = MultipartBody.Part.createFormData("file", FILE.getName(), requestBody);
                call = service.upload(URL, body);
                break;
            default:
                break;
        }

        if(call != null)
        {
            call.enqueue(getRequestCallbacks());
        }
    }

    private Callback<String> getRequestCallbacks() {
        return new RequestCallbacks(REQUEST, SUCCESS, ERROR, FAILURE, DIALOG);
    }

    public final void get() {
        request(HttpMethod.GET);
    }

    public final void post() {
        if(BODY == null) {
            request(HttpMethod.POST);
        } else {
            if(!PARAMS.isEmpty())
            {
                throw new RuntimeException("post params must be null!");
            }
            request(HttpMethod.POST_RAW);
        }
    }

    public final void put() {
        if(BODY == null) {
            request(HttpMethod.PUT);
        } else {
            if(!PARAMS.isEmpty())
            {
                throw new RuntimeException("put params must be null!");
            }
            request(HttpMethod.PUT_RAW);
        }
    }

    public final void delete() {
        request(HttpMethod.DELETE);
    }

    public final void upload() {
        request(HttpMethod.UPLOAD);
    }

    public final void download() {
        new DownloadHandler(URL, REQUEST, DOWNLOAD_DIR, EXTENSION, NAME,
                SUCCESS, FAILURE, ERROR)
                .handleDownload();
    }
}
